package org.momonga1banchi.reminder.server;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.mail.Address;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Part;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.momonga1banchi.reminder.util.DateUtil;
import org.momonga1banchi.reminder.util.MailUtil;
import org.momonga1banchi.reminder.util.MyLog;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;

/**
 * リマインド登録サーブレット
 *
 * @author momonga1banchi
 * @since 2010/05/18
 */
@SuppressWarnings("serial")
public class RegisterServlet extends HttpServlet {
    private DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
    private Properties props = new Properties();
    private Session session = Session.getDefaultInstance(props, null);
    private MimeMessage msg = null;

    public void doPost(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
        try {
            msg = new MimeMessage(session, req.getInputStream());
            Address to = msg.getFrom()[0];
//            MyLog.log.info("to:" + to.toString());
            String date = msg.getSubject();
//            MyLog.log.info("subject:" + date);

            // TODO 日付処理は後でユーティリティに切り出す。
            // 日付調整用変数。　年、月、日、時、分を表す。それぞれの値の増減を行う。
            int[] dateAdjuster = { 0, 0, 0, 0, 0 };
            // 日付調整実施
            if (date != null) {
                // 月の調整
                if (date.contains("来月")) {
                    dateAdjuster[1] = 1;
                }
                // TODO 日の調整 ・・・　曜日（月〜日）指定の設定も後ほど行う。
                if (date.contains("明日")) {
                    dateAdjuster[2] = 1;
                } else if (date.contains("明後日")) {
                    dateAdjuster[2] = 2;
                } else if (date.contains("来週")) {
                    dateAdjuster[2] = 7;
                }
                // 時の調整
                Pattern hourPattern = Pattern.compile("([0-9０-９]{1,2})時間[^後]*後");
                Matcher hourMatcher = hourPattern.matcher(date);
                if (hourMatcher.find()) {
                    String hour = hourMatcher.group(1);
                    hour.replaceAll("０", "0").replaceAll("１", "1").replaceAll("２", "2").replaceAll("３", "3")
                            .replaceAll("４", "4").replaceAll("５", "5").replaceAll("６", "6").replaceAll("７", "7")
                            .replaceAll("８", "8").replaceAll("９", "9");
                    dateAdjuster[3] = Integer.valueOf(hour);
                }
                // 分の調整
                Pattern minutePattern = Pattern.compile("([0-9０-９]{1,3})分後");
                Matcher minuteMatcher = minutePattern.matcher(date);
                if (minuteMatcher.find()) {
                    String minute = minuteMatcher.group(1);
                    minute.replaceAll("０", "0").replaceAll("１", "1").replaceAll("２", "2").replaceAll("３", "3")
                            .replaceAll("４", "4").replaceAll("５", "5").replaceAll("６", "6").replaceAll("７", "7")
                            .replaceAll("８", "8").replaceAll("９", "9");
                    dateAdjuster[4] = Integer.valueOf(minute);
                }
            }

            String name = MailUtil.getMailBodyMessage((Part) msg);
//            MyLog.log.info("taskname:" + name);

            if (name == null || name.equals("")) {
                name = "having something to do";
            } else if (name.length() > 500) {
                name = name.substring(0, 500);
            }

            String printDate = "";

            try {
                Calendar scheduledTime = DateUtil.getDate(date);

                // 時刻の調整
                scheduledTime.add(Calendar.MONTH, dateAdjuster[1]);
                scheduledTime.add(Calendar.DAY_OF_MONTH, dateAdjuster[2]);
                scheduledTime.add(Calendar.HOUR_OF_DAY, dateAdjuster[3]);
                scheduledTime.add(Calendar.MINUTE, dateAdjuster[4]);

                SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmm");
                String dbDate = sdf.format(scheduledTime.getTime());
                SimpleDateFormat timeParser = new SimpleDateFormat("yyyyMMddHHmm");
                SimpleDateFormat timePrinter = new SimpleDateFormat("yyyy/MM/dd(EEE) HH:mm");

                printDate = timePrinter.format(timeParser.parse(dbDate));
                Entity task = new Entity("task", dbDate + to);
                task.setProperty("date", dbDate);
                task.setProperty("to", to.toString());
                task.setProperty("name", name);
                task.setProperty("done", false);
                ds.put(task);
            } catch (Exception e) {
//                MyLog.log.warn("error occured " + e.getMessage());
                MimeMessage replyMsg = new MimeMessage(session);
                replyMsg.setFrom(new InternetAddress("reply@scotethu.com",
                        "reply@scotethu.com"));
                replyMsg.setRecipient(Message.RecipientType.TO, to);
                replyMsg.setSubject("your request failed", "iso-2022-jp");
                replyMsg.setText("Sorry, we cannot accept your request.\nPlease try again.", "iso-2022-jp");
                Transport.send(replyMsg);
                return;
            }

            MimeMessage replyMsg = new MimeMessage(session);
            replyMsg.setFrom(new InternetAddress("reply@scotethu.com",
                    "reply@scotethu.com"));
            replyMsg.setRecipient(Message.RecipientType.TO, to);
            replyMsg.setSubject("recieved your request", "iso-2022-jp");
            replyMsg.setText("We will accept your request as follows.\ndate:" + printDate + "\n" + name, "iso-2022-jp");
            Transport.send(replyMsg);

        } catch (MessagingException e) {
//            MyLog.log.warn("error occured " + e.getMessage());
        }

    }

}
